package com.zx._01_基础._012_反射;

import java.beans.BeanInfo;
import java.beans.EventSetDescriptor;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.beanutils.BeanUtils;
import org.junit.Test;

public class 操作类的属性 {

    /**
     * Introspector --> 内省，用来得到某个javabean的BeanInfo
     * BeanInfo --> 就是javabean的描述类，用来描述javabean的结构！作用：得到javabean的所有属性描述类
     * PropertyDescriptor --> 可以用来获取属性的读写方法
     * Method --> 可通过invoke来调用方法。
     */
    @Test
    public void fun1() throws Exception {
        // 通过内省得到BeanInfo
        BeanInfo beanInfo = java.beans.Introspector.getBeanInfo(ReflectModel.class);

        // 通过BeanInfo得到所有属性的描述符
        PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();

        for (PropertyDescriptor pd : pds) {
            System.out.println(pd.getName());
        }

        Method m = pds[1].getWriteMethod();
        Object o = ReflectModel.class.newInstance();
        m.invoke(o, "zhangSan");

        System.out.println(o);
    }

    @Test
    public void test01() throws IntrospectionException, InvocationTargetException, IllegalAccessException {
        // 得到Student类中的属性，被封装到了BeanInfo中
        BeanInfo beanInfo = Introspector.getBeanInfo(ReflectModel.class);
        // 获得所有的属性，根据get方法获得的属性
        PropertyDescriptor[] ps = beanInfo.getPropertyDescriptors();
        // 获得所有的方法
        MethodDescriptor[] ms = beanInfo.getMethodDescriptors();
        // 获得所有的事件
        EventSetDescriptor[] es = beanInfo.getEventSetDescriptors();

        //例如：
        //1.定义一个空对象
        ReflectModel s = new ReflectModel();
        //2.定义一个属性控制器，代表Student中的name属性
        PropertyDescriptor pd = new PropertyDescriptor("name", ReflectModel.class);
        //3.得到属性的get方法
        Method m = pd.getReadMethod();
        //4.执行get方法
        String value = (String) m.invoke(s, null);
        System.out.println(value);
        //5.得到属性的set方法
        Method m1 = pd.getWriteMethod();
        //6.执行属性的set方法，并传入参数
        m1.invoke(s, "王翔云");
        System.out.println(s.getName());
    }

    @Test
    public void test02() throws Exception {
        String className = ReflectModel.class.getName();
        // 1. 得到Class
        Class c = Class.forName(className);
        //2. 通过Class对象创建实例
        Object o = c.newInstance();
        //3. 给对象的属性赋值
        //BeanUtils在设置属性时，会做类型转换！ 当类型转换失败时，它也不会抛出异常！
        BeanUtils.setProperty(o, "name", "张三");
        // 当javabean不存在这个属性时！那么只是设置失败，不会有异常！
        BeanUtils.setProperty(o, "xxx", "XXX");

        System.out.println(BeanUtils.getProperty(o, "name"));
        System.out.println(o);

        //map中的key与javaBean的属性名相同
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("name", "liSi");
        map.put("age", "89");

        ReflectModel p = new ReflectModel();
        //一次把map中所有数据封装到javaBean中
        BeanUtils.populate(p, map);
        System.out.println(p);
    }

}
